Java アプリケーションのメモリリークを調査する強力なツールである Eclipse Memory Analyser Tool を使用して、XPages アプリケーションのメモリリークを調査する方法について紹介します。
Java ヒープダンプは、Java 仮想マシンのヒープメモリにある Java オブジェクトの現在の状態ダンプです。ヒープダンプはバイナリのデータで、それを読むためには Eclipse Memory Analyser Tool (www.eclipse.org/mat) が必要になります。
Domino で取得できるヒープダンプは IBM JVM のヒープダンプフォーマットで書かれているため、Eclipse Memory Analyser Tool に IBM の提供するプラグインである IBM Diagnostic Tool Framework for Java Version 1.10 (http://www.ibm.com/developerworks/java/jdk/tools/dtfj.html) を追加する必要があります。
Eclipse Memory Analyzer Tool は Eclipse IDE のプラグインとしても、単体の RCP プログラムとしても公開されています。
ここでは Eclipse IDE のプラグインとして構成し、さらに IBM Diagnostic Tool Framework for Java を追加でインストールする方法を紹介します。
この記事では実際に XPages アプリケーションでメモリリークを起こさせて、それが MAT でどのように発見できるかを見てみます。試した環境は以下になります。
サンプルとして使用するのは以下のような XPage アプリケーションです。このアプリションでは入力フィールドに設定されたサイズの配列のデータを作成しスコープ変数の applicationScope 変数に値を設定します。アプリケーションスコープの変数は、XPages アプリケーションとしてデータを保持するので、大きな値を設定することでメモリを圧迫させることができます。この記事での動作確認では入力フィールドに「500」を設定し、500MB のデータを生成しました。
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:label value="Leak data size: " id="label1"></xp:label>
<xp:inputText id="inputRepeatCount" required="true">
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
<xp:this.validators>
<xp:validateRequired message="Data size is mandatory,"></xp:validateRequired>
<xp:validateLongRange minimum="1" maximum="1000"></xp:validateLongRange>
</xp:this.validators>
</xp:inputText>
<xp:label value="MB" id="label2"></xp:label>
<xp:button value="Generate Memory Leak" id="buttonGenMemLeak">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="panelMessage">
<xp:this.action><![CDATA[#{javascript:
var repeat = getComponent("inputRepeatCount").getValue();
print ("Generating memory leak with " + repeat + " MB.");
var testdata_16 = "0123456789ABCDEF";
var testdata_1024 = "";
for (i=0; i<64; i++) {
testdata_1024 = testdata_1024 + testdata_16;
}
var listsize = 1024 * repeat;
var list = new Array(listsize);
for (j=0; j< listsize; j++) {
list[j] = testdata_1024;
}
applicationScope.testdatalist = list;
viewScope.message = list.length + "x1024 bytes data was stored in applicationScope.";
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
 
<xp:button value="Clear Memory Leak" id="buttonClearMemLeak">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" disableValidators="true" refreshId="panelMessage">
<xp:this.action><![CDATA[#{javascript:
applicationScope.testdatalist = null;
viewScope.message = "ApplicationScope data is cleared.";
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:panel id="panelMessage">
<xp:text escape="true" id="computedField1" value="#{viewScope.message}"></xp:text>
</xp:panel>
</xp:view>